package com.gdufe.studytogether.utils;

import com.alibaba.druid.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class DirtyWorldFilter {
    public static Node dicts=new Node();//前缀树的根节点


    //叶子节点
    public static final Node LAST_NODE=new Node(true);

    static {
        String[] dirtyWords=new String[]{"智障","傻逼","去死","自杀","杀人","笨蛋"};
        ArrayList<String> strings = new ArrayList<>(Arrays.asList(dirtyWords));
        batchPutDicts(strings);
    }

    public static String doFilter(String text){
        if (StringUtils.isEmpty(text)){
            return text;
        }
        Node map=dicts;
        int beginIndex=-1;//记录开始下标
        int end=-1;
        char[] chars = text.toCharArray();
        for (int i = 0; i < text.length(); i++) {
            char c = chars[i];
            if (!isChinese(c)){//过滤非中文字符
                continue;
            }
            Node nextNode = map.get(c);
            if (nextNode!=null){
                //存在下一个状态
                if (beginIndex==-1){
                    beginIndex=i;//记录起始下标
                }
                if (nextNode.isEnd){
                    end=i;//当前为最终状态
                }
                if (nextNode==LAST_NODE){
                    //进行敏感词替换
                    for (int j = beginIndex; j <=end; j++) {
                        chars[j]='*';
                    }
                    beginIndex=-1;
                    end=-1;
                    map=dicts;
                    continue;
                }
                map=nextNode;//状态转移
            }else {
                //不存在下一个状态
                if (beginIndex!=-1){
                    //检查起止位置，进行敏感词替换
                    if (end!=-1){
                        for (int j = beginIndex; j <=end; j++) {
                            chars[j]='*';
                        }
                        end=-1;
                    }
                    beginIndex=-1;
                }
                //恢复初始状态
                if (map!=dicts){
                    map=dicts;
                    i--;//使用原字典查看
                }
            }
        }
        //处理文本最后一个敏感词
        if (beginIndex!=-1){
            if (end!=-1){
                for (int j = beginIndex; j <=end; j++) {
                    chars[j]='*';
                }
            }
        }
        return new String(chars);
    }


    //批量添加敏感词
    public static void batchPutDicts(List<String> words){
        for (String str:words){
            putStringIntoDicts(str);
        }
    }


    //添加单个敏感词
    public static void putStringIntoDicts(String str){
        char[] chars = str.toCharArray();
        Node node=dicts;
        for (int i = 0; i < str.length(); i++) {
            char ch=chars[i];
            Node nextNode = node.get(ch);
            if (nextNode!=null){
                if (nextNode==LAST_NODE){
                    if (i!=str.length()-1){
                        //不是最后一个字符
                        Node node1 = new Node(true);
                        node.put(ch,node1);
                        nextNode=node1;
                    }
                }
                node=nextNode;
            }else {
                Node newNode;
                if (i==str.length()-1){
                    newNode=LAST_NODE;
                }else {
                    newNode=new Node();
                }
                node.put(ch,newNode);
                node=newNode;
            }
        }
    }

    public static boolean isChinese(char ch) {
        // 判断字符是否在汉字的Unicode范围内
        return (ch >= '\u4e00' && ch <= '\u9fa5') || // 汉字
                (ch >= '\u3400' && ch <= '\u4DBF')  // 扩展 A
                ;
    }


    public static class Node extends HashMap<Character,Node>{
        boolean isEnd;//是否是一个结束位置

        public Node(boolean isEnd) {
            super();
            this.isEnd = isEnd;
        }

        public Node(){
            super();
            this.isEnd=false;
        }

        public boolean isEnd() {
            return isEnd;
        }

        public void setEnd(boolean end) {
            isEnd = end;
        }

    }
}
